home *** CD-ROM | disk | FTP | other *** search
/ Almathera Ten Pack 3: CDPD 3 / Almathera Ten on Ten - Disc 3: CDPD3.iso / fish / 001-100 / 001-025 / 020 / hd / hd.c next >
C/C++ Source or Header  |  1995-03-17  |  13KB  |  383 lines

  1. /*  Dump files, similar to OD, but in a different format
  2.  *  Files are displayed sixteen bytes to a line, offset from the beginning
  3.  *  of the file on the right, hex values in the middle,
  4.  *  ascii values on the right.
  5.  *  -c option displays char value above hex value
  6.  *  13 May 1985 David Elins
  7.  */
  8.  
  9. /* modifications
  10.  * 3-28-86  uses different formats depending on how bytes are ordered
  11.  *      on the machine
  12.  *      little-endian (e.g. vax)
  13.  *      hex ..... hex addr ascii
  14.  *      big endian (e.g. 68000)
  15.  *      addr hex ascii
  16.  *
  17.  *      idea came from an article by Mike Higgins
  18.  *      in "Computer Language" April, 1986
  19.  *
  20.  * 3-30-86  -x option reverses natural display format
  21.  *
  22.  * 4-14-86  Amiga port for both Lattice and Manx (under 32 bit)
  23.  *
  24.  *    screen width needs to be a define
  25.  *    fputs not documented to return valid value except on error
  26.  *    printf return value cannot be relied on under Lattice
  27.  *    modify isprint semantics to limit to "normal" ascii
  28.  *
  29.  */
  30. #include <stdio.h>
  31. #include <ctype.h>
  32. extern char *strrchr();
  33. extern void exit();
  34. #define EQS(str1,str2) (strcmp((str1),(str2))==0)
  35.  
  36. /*
  37.  *  On the Amiga, the normal CLI window is only 77 characters wide.
  38.  *  I decided to trim the line length by recovering 3 characters from
  39.  *  the offset field.  Fred Fish   14-Apr-86
  40.  */
  41.  
  42. #ifdef AMIGA
  43. #define OFFSETFMT "%05lx"
  44. #define OFFSETSIZ (5)        /* Should match length in OFFSETFMT */
  45. #define WIDTH (77)        /* Screen width in char positions */
  46. #define BLANKS "     "
  47. #define ISPRINT(x) (((x) < 0200) && isprint(x))    /* Limit to 000-177 */
  48. extern int Enable_Abort;
  49. #else
  50. #define OFFSETFMT "%08lx"
  51. #define OFFSETSIZ (8)
  52. #define WIDTH (80)
  53. #define BLANKS "        "
  54. #define ISPRINT(x) isprint(x)
  55. #endif
  56.  
  57. static int showchar=0;
  58. static int manyfile;
  59.  
  60. main(argc, argv)
  61. int argc;
  62. char *argv[];
  63. {
  64. #ifdef MSDOS
  65.     char *pgmname="hd"; /* Microsoft C may not support argv[0] */
  66. #else
  67.     extern char *basename(); /* pathnames allowed on commands */
  68.     char *pgmname=basename(argv[0]);
  69. #endif
  70.     int lowfirst(),highfirst(); /* dump formatting routines */
  71.     static int reverse = 0; /* reverse natural display format */
  72.     register char *cp, c;
  73.  
  74. #ifdef AMIGA
  75.     Enable_Abort = 1;    /* Stupid Lattice default is 0 */
  76. #endif
  77.     /* parse options */
  78.     for (; argc > 1 && (*argv[1] == '-'); argv++, argc--) {
  79.         cp = &argv[1][1];   /* - alone is standard input */
  80.         while ((c = *cp++) && argc) {
  81.             switch (c) {
  82.                 case 'c':   /* like od -c option */
  83.                     showchar = 1;
  84.                     break;
  85.                 case 'x':   /* reverse natural display format */
  86.                     reverse = 1;
  87.                     break;
  88.                 default:
  89.                     argc=0; /* modify argument to indicate error */
  90.                     break;
  91.             }
  92.         }
  93.     }
  94.  
  95.     if (argc < 1) {
  96.         (void)fprintf(stderr,"Usage: %s [-cx] [files]\n", pgmname);
  97.         exit(1);
  98.     }
  99.  
  100.     manyfile = (argc > 2);              /* more than one file to display? */
  101.     /*  loop through filename arguments
  102.         if reverse == 1, exclusive or'ing with it
  103.         will reverse the return value of bytorder()
  104.      */
  105.     if (bytorder() ^ reverse)   /* display in natural or reversed order */
  106.         exit(filter(argc,argv,lowfirst));
  107.     else
  108.         exit(filter(argc,argv,highfirst));
  109. }
  110.  
  111. /* format and display contents of stdin */
  112. /* low addr byte of multibyte values is MOST significant */
  113. static int
  114. highfirst(filename)     /* format and display contents of stdin */
  115. char *filename;
  116. {
  117.     unsigned char   /* is unsigned char portable ? */
  118.         buf[16],    /* portion of file read */
  119.         *bufptr,    /* pointer into that portion */
  120.         ascstr[17], /* ascii equivalents of digits */
  121.         *pascstr;   /* pointer into above string */
  122.     int ctr,        /* general counter */
  123.         col,        /* current column printed */
  124.         rlen;       /* length read */
  125.     long offset=0L; /* offset from beginning of file */
  126.     static char sep[]="::::::::::::::"; /* separates filenames */
  127.  
  128.     if (manyfile)
  129.         (void)printf("%s\n%s\n%s\n", sep, filename, sep);
  130.  
  131.     /* read a display line's worth at a time, format and display it */
  132.     while ((rlen = fread(buf, sizeof(char), sizeof(buf), stdin)) > 0) {
  133.  
  134.     col = 1;
  135.         bufptr = buf;   /* point to beginning of bytes read */
  136.  
  137.         if (showchar) { /* print equivalent characters above hex values? */
  138.             (void)fputs(BLANKS, stdout);    /* for offset into file; */
  139.             for (ctr = 0; ctr < rlen; ctr++) {
  140.                 if (ctr % 4 == 0)
  141.                     (void)fputs(" ",stdout);    /* separate each four bytes */
  142.                 (void)fputs(" ",stdout);
  143.                 if (*bufptr == '\b')
  144.                     (void)fputs("\\b",stdout);
  145.                 else if (*bufptr == '\t')
  146.                     (void)fputs("\\t",stdout);
  147.                 else if (*bufptr == '\n')
  148.                     (void)fputs("\\n",stdout);
  149.                 else if (*bufptr == '\f')
  150.                     (void)fputs("\\f",stdout);
  151.                 else if (*bufptr == '\r')
  152.                     (void)fputs("\\r",stdout);
  153.                 else if (ISPRINT(*bufptr))
  154.                     (void)printf(" %c", *bufptr);
  155.                 else
  156.                     (void)fputs("  ",stdout);
  157.                 bufptr++;
  158.             }
  159.             (void)putc('\n',stdout);
  160.         }
  161.                 
  162.         bufptr = buf;   /* point to beginning of bytes read */
  163.         pascstr = ascstr; /* point to beginning of ascii equivalents */
  164.  
  165.         (void) printf(OFFSETFMT, offset); /* count and print offset into file; */
  166.     col += OFFSETSIZ;
  167.         for (ctr = 0; ctr < rlen; ctr++) {
  168.             if (ctr % 4 == 0) {
  169.                 col++;        /* fputs value defined only on error */
  170.         (void)fputs(" ",stdout);   /* separate each four bytes */
  171.         }
  172.             *pascstr++ = ISPRINT(*bufptr) ? *bufptr : '.';  /* save ascii val */
  173.             (void) printf(" %02x", *bufptr++);  /* display hex value of byte */
  174.         col += 3;
  175.         }
  176.         *pascstr = '\0';    /* terminate ascii string */
  177.     do {
  178.         (void)fputs(" ",stdout);    /* fputs value defined only on error */
  179.     } while (col++ < (WIDTH-18));        /* align ascii values */
  180.         (void)printf("|%s|\n",ascstr);              /* display ascii values */
  181.         offset += rlen;                     /* bump offset into file */;
  182.         }
  183.     return (1);
  184. }
  185.  
  186. /* format and display contents of stdin */
  187. /* low addr byte of multibyte values is LEAST significant */
  188. static int
  189. lowfirst(filename)      /* format and display contents of stdin */
  190. char *filename;
  191. {
  192.     unsigned char   /* is unsigned char portable ? */
  193.         buf[16],    /* portion of file read */
  194.         *bufptr,    /* pointer into that portion */
  195.         *rbufptr,   /* backward pointer into that portion */
  196.         ascstr[17], /* ascii equivalents of digits */
  197.         *pascstr;   /* pointer into above string */
  198.     int ctr,        /* general counter */
  199.         col,        /* current column printed */
  200.         rlen;       /* length read */
  201.     long offset=0L; /* offset from beginning of file */
  202.     static char sep[]="::::::::::::::"; /* separates filenames */
  203.  
  204.     if (manyfile)
  205.         (void)printf("%s\n%s\n%s\n", sep, filename, sep);
  206.  
  207.     /* read a display line's worth at a time, format and display it */
  208.     while ((rlen = fread(buf, sizeof(char), sizeof(buf), stdin)) > 0) {
  209.  
  210.     col = 1;    /* current printed column */
  211.         rbufptr = buf + rlen - 1;   /* point to end of bytes read */
  212.  
  213.         if (showchar) { /* print equivalent characters above hex values? */
  214.             for (ctr = 0; ctr < sizeof(buf); ctr++) {
  215.                 if ((ctr + rlen) < sizeof(buf))
  216.                     (void)fputs("  ",stdout);
  217.                 else if (*rbufptr == '\b')
  218.                     (void)fputs("\\b",stdout);
  219.                 else if (*rbufptr == '\t')
  220.                     (void)fputs("\\t",stdout);
  221.                 else if (*rbufptr == '\n')
  222.                     (void)fputs("\\n",stdout);
  223.                 else if (*rbufptr == '\f')
  224.                     (void)fputs("\\f",stdout);
  225.                 else if (*rbufptr == '\r')
  226.                     (void)fputs("\\r",stdout);
  227.                 else if (ISPRINT(*rbufptr))
  228.                     (void)printf(" %c", *rbufptr);
  229.                 else
  230.                     (void)fputs("  ",stdout);
  231.                 if (ctr % 4 == 3)
  232.                     (void)fputs(" ",stdout);    /* separate each four bytes */
  233.                 (void)fputs(" ",stdout);
  234.                 if ((ctr + rlen) >= sizeof(buf))
  235.                     rbufptr--;
  236.             }
  237.             (void)putc('\n',stdout);
  238.         }
  239.                 
  240.         bufptr = buf;   /* point to beginning of bytes read */
  241.         rbufptr = buf + rlen - 1;   /* point to end of bytes read */
  242.         pascstr = ascstr; /* point to beginning of ascii equivalents */
  243.  
  244.         for (ctr = 0; ctr < sizeof(buf); ctr++) {
  245.             if ((ctr + rlen) < sizeof(buf)) { /* display hex value of byte */
  246.         (void) fputs("   ",stdout); /* no value */
  247.             } else {
  248.                 (void) printf("%02x ", *rbufptr);
  249.         }
  250.         col += 3;
  251.             if (ctr % 4 == 3) {
  252.                 col++;
  253.         (void) fputs(" ",stdout);   /* separate each four bytes */
  254.         }
  255.             if ((ctr + rlen) >= sizeof(buf)) {  /* save ascii value */
  256.                 *pascstr++ = ISPRINT(*bufptr) ? *bufptr : '.';
  257.                 bufptr++;   /* advance, */
  258.                 rbufptr--;  /* decrement pointers */
  259.             }
  260.         }
  261.         *pascstr = '\0';    /* terminate ascii string */
  262.         (void) printf(OFFSETFMT,offset); /* count and print offset into file; */
  263.     col += OFFSETSIZ;
  264.     do {
  265.         (void)fputs(" ",stdout);    /* fputs value defined only on error */
  266.     } while (col++ < (WIDTH-18));        /* align ascii values */
  267.         (void)printf("|%s|\n",ascstr);              /* display ascii values */
  268.         offset += rlen;                     /* bump offset into file */;
  269.         }
  270.     return (1);
  271. }
  272.  
  273. /* is low addr byte of multi-byte values the least significant ? */
  274. static int
  275. bytorder()
  276. {
  277.     static union {  /* used to determine byte order */
  278.         int x;
  279.         char c[2];
  280.     }   test;
  281.  
  282.     test.x=1;   /* find out how bytes are ordered */
  283.     return(test.c[0] == test.x);
  284. }
  285.  
  286. /*
  287.  *      perform the basename(1) function from a C program
  288.  */
  289. static
  290. char *
  291. basename(name)  /* return pointer to filename portion of name */
  292. char name[];
  293. {
  294.     char *cp=strrchr(name,'/');
  295.  
  296.     return(cp==NULL ? name : (cp+1));
  297. }
  298.  
  299. /*
  300.  *  loop through filenames on a command line
  301.  *  reopening each as standard input
  302.  */
  303. extern int errno; /* system error variable */
  304. extern void perror();
  305.  
  306. static
  307. int
  308. filter(argc,argv,process)
  309. int argc;       /* how many command line arguments */
  310. char *argv[];   /* command line arguments */
  311. int (*process)();/* function that processes each file, called at least once */
  312.                  /* the only argument is the filename (NULL if orig stdin) */
  313. {
  314. #ifdef unix
  315.     register int fd = dup(0);   /* initial standard input */
  316. #endif
  317.     register int inorig;        /* 0=from stdin, else from file */
  318.     register int firstime;      /* make sure *process is called once */
  319.     register int retval=0;      /* return value */
  320.  
  321.     for (firstime = 1; firstime || (argc > 1); argc--,argv++,firstime=0) {
  322.         /* arguments are filenames to filter, "-" means standard input */
  323.  
  324.         inorig = ((argc == 1) || EQS(argv[1],"-"));
  325.         if (inorig) {
  326. #ifdef unix
  327.             (void)close(0); /* reset to initial standard input */
  328.             (void)dup(fd);
  329. #endif
  330.         }
  331.         /* set filename as standard input */
  332.         else if (freopen(argv[1],"r",stdin) == NULL) {
  333.             char string[48];
  334.             retval = errno; /* return if error */
  335.             (void)sprintf(string,"cannot open %s", argv[1]);
  336.             perror(string);
  337.             break;
  338.         }
  339.  
  340.         (*process)(inorig?(char *)NULL:argv[1]);    /* process this file */
  341.     }
  342.  
  343.     if (!inorig) {  /* leave stdin the same file as at entry */
  344. #ifdef unix
  345.         (void)close(0);
  346.         (void)dup(fd);
  347. #endif
  348.     }
  349.  
  350.     return(retval);
  351. }
  352.  
  353. #ifdef MANX
  354.  
  355. char *strrchr (s, c)
  356. char *s;
  357. char c;
  358. {
  359.     register char *scan;
  360.  
  361.     scan = s;
  362.     while (*scan++ != '\000') {;}
  363.     while (--scan > s && *scan != c) {;}
  364.     return (*scan == c ? scan : NULL);
  365. }
  366.  
  367. #endif    /* MANX */
  368.  
  369. #ifdef AMIGA    /* Neither Lattice or Manx has perror */
  370.  
  371. void perror (sp)
  372. char *sp;
  373. {
  374.     if (sp && *sp) {
  375.         fprintf (stderr, "%s: ", sp);
  376.     }
  377.     fprintf (stderr, "<unknown error>\n");
  378. }
  379.  
  380. #endif /* AMIGA */
  381.  
  382.     
  383.